<?php

class Event_CallCenterPostSave extends Crud_Event_Handler
{
	protected $_type = 'postSave';
	protected $_changed = 0;

	/**
	 * Run handler with options array.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	public function run($row)
	{

		$sectionRow = $row;
		#$placed = OrdersService::getInstance()->getOrderStatusByKey(OrdersService::STATUS_ORDER_PLACED);

		if ($row instanceof Crud_Section_Row) {
			$row = $row->getRow();
		}

		if ($this->_getParam('action') == 'add') {
			$row->addLog('%s создал заказ');

			$user = $this->_getAdminUser();
			$row->setAdminUserId($user->getId());
		}

		//$this->_wikimart($row);

		$this->_delivery($row);
		$this->_comment($row);
		#if($row->getOrderStatusId() == $placed->getId()){
			if(!$this->_getParam('copy') && !$this->_getParam('canceled_copy')){
				$this->_deliveryCost($row);
			}
		#}
		if ($this->_getParam('copy')) {
			$this->_copy($row);
		}
		
		if ($this->_getParam('canceled_copy')) {
			$this->_cancelCopy($row);
		}

		$this->_order2product($row);


		$this->_toFile($row);

		Service_Base::redirectToTable($this->_getParam('fromtable'), $sectionRow, true);
	}

	protected function _deliveryCost($row)
	{
		$params = array("city"=>$this->_getParam('city'),
						"in_city"=>$this->_getParam('inMkad'),
						"sum"=>$row->getTotalCost(),
						"weight"=> $row->getWeight()
						);
		$row->setDeliveryCost(DeliveryService::getInstance()->getDeliveryCost($params));
		$row->save();
	}

	/**
	 * Замена type_id у заказа, если поле викимарт установлено.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _wikimart($row)
	{
		if (!$row->getWikimart()) {
			return ;
		}

		$peer = OrderTypePeer::getInstance();
		$select = OrderTypePeer::getInstance()->select();
		$select->where("`order_type`.`key` = 'wikimart'");
		$wiki = $peer->fetchRow($select);

		$row->setTypeId($wiki->getId());
		$row->save();
	}

	protected function _cancelCopy($row){
		if($row->isPlaced() || $row->isUncall() || $row->isWaitPaidCard()) {

			$row->setStatus(OrdersService::STATUS_ORDER_CANCELED_COPY);
			$row->save();

			$this->_copy($row, "cancelCopy");

			$configMail = Config::getInstance()->mail;
			if ($configMail->enabled) {
				$subj = "Отмена заказа с копией {$row->getId()}";
				if ($row->isTransferedToDelivery()) {
					$suffix = $row->getOrderOperatorRowByOperatorId()->getName();
					$suffix = ' в логистической компании ' . $suffix;
					$subj .= $suffix;
				}

				$message = $subj . $configMail->sign;
				$mail = new Zend_Mail('UTF-8');
				$mail->setHeaderEncoding(Zend_Mime::ENCODING_BASE64);
				$mail->setSubject($subj);
				$mail->setBodyHtml($message);
				$mail->addTo('order@detmir.ru');
				$mail->send();
			}
		}
	}


	/**
	 * Copy order.
	 *
	 * @param OrdersRow $orw
	 * @return void
	 */
	public function _copy($row, $status='default')
	{
		$nRow = OrdersPeer::getInstance()->createRow();

		$data = $row->toArray();
		$filter = new Zend_Filter_Word_UnderscoreToCamelCase();
		$notCopy = array('id', 'created_at', 'executed_at', 'payment_method_id', 'type_id', 'order_status_id', 'total_price', 'total_cost', 'percent', 'type_discount');
		foreach ($data as $key => $value) {
			if (in_array($key, $notCopy)) continue;
			if ($value === null) continue;

			$method = $filter->filter($key);
			$method = ucfirst($method);
			$method = 'set' . $method;
			$nRow->$method($value);
		}

		// Set name
		$nRow->setFio($this->_getParam('firstName') . ' ' . $this->_getParam('lastName'));

		// Set payment method to cash
		$payment = PaymentMethodsPeer::getInstance()->fetchByKey('cash');
		$nRow->setPaymentMethodId($payment->getId());

		// Set order type to operator
		$type = OrderTypePeer::getInstance()->fetchByKey('operator');
		$nRow->setTypeId($type->getId());

		// Set order status to placed
		$accepted = OrderStatusPeer::getInstance()->fetchByKey('placed');
		$nRow->setOrderStatusId($accepted->getId());

		// Устанавливаем оператора, который является ответственным за новый заказ
		$user = $this->_getAdminUser();
		$nRow->setAdminUserId($user->getId());

		//устанавливаем родителя копии
		$nRow->setCopyParentId($row->getId());

		$nRow->save();
		$id = $nRow->getId();

		$front = Zend_Controller_Front::getInstance();
		$router = $front->getRouter();
		$url = $router->assemble(array('id' => $id));

		//копируем состав заказа
		if($status != "cancelCopy"){
			$this->_copyProduct($row->getId(), $nRow->getId());
		}else{
			$this->_cancelCopyProduct($row->getId(), $nRow->getId());
		}


		$nRow->addLog("%s скопировал заказ с {$row->getId()}");
		$row->addLog("%s сделал копию этого заказа ({$nRow->getId()})");

		$connection = Db::getConnection();
		$connection->commit();

		$table = $this->_getParam('fromtable');
		if (!empty($table)) {
			$url .= '?fromtable='.$table;
		}
		header("Location: $url");
		exit($url);
	}

	protected function _cancelCopyProduct($order_id, $new_order_id)
	{
		$order2product = Order2productPeer::getInstance();
		$select = $order2product->select()->where('`order_id` = ?', $order_id);
		$result = $order2product->fetchAll($select);

		$order = OrdersPeer::getInstance()->fetchById($new_order_id);
		$this->_copyDelivery($order, $new_order_id);
		
		foreach($result as $item){
			$data = array(
				'order_id'=>$new_order_id,
				'product_id'=>$item['product_id'],
				'count'=>$item['count'],
				'desired_count'=>$item['desired_count'],
				'price'=>$item['price'],
				'clean_price'=>$item['clean_price'],
				'product_tarif_id'=>$item['product_tarif_id']
			);
			$order2product->insert($data);
		}
	}

	protected function _copyDelivery($order, $new_order_id){
		$delivery = DB::getConnection()->fetchRow("SELECT * FROM `delivery` WHERE `id`=".$order['delivery_id']);

		$new_delivery = array();
		foreach($delivery as $key=>$value){
			if($key != 'id'){
				if($key == 'in_mkad'){
					$new_delivery[$key] = 0;
				}else{
					$new_delivery[$key] = $value;
				}
			}
		}

		$insert_id = DeliveryPeer::getInstance()->insert($new_delivery);
		DB::getConnection()->query("UPDATE `orders` SET `delivery_id`=".$insert_id." WHERE id=".$new_order_id);
	}

	protected function _copyProduct($order_id, $new_order_id)
	{
		$order2product = Order2productPeer::getInstance();
		$select = $order2product->select()->where('`order_id` = ?', $order_id);
		$result = $order2product->fetchAll($select);

		$order = OrdersPeer::getInstance()->fetchById($new_order_id);
		$this->_copyDelivery($order, $new_order_id);
		
		$product = ProductPeer::getInstance();
		$product_id_order = array();
		$total_cost = 0;
		foreach($result as $item)
		{
			$select = $product->select();
			$select->where('id = ?', $item['product_id']);
			$pro_result = $product->fetchRow($select);
			//Высчитываем остаток для продуктов
			$ost = 0;
			$counts = 0;
			if($pro_result['count'] > $item['count']){
				$ost = $pro_result['count'] - $item['count'];
				if($ost >= $item['count'])
				{
					$counts = $item['count'];
				}
				if($ost <= $item['count'])
				{
					$counts = $ost;
				}
			}else{
				$counts = $pro_result['count'];
			}

				$data = array(
					'order_id' => $new_order_id,
					'product_id' => $pro_result['id'],
					'count' => $counts,
					'desired_count' => $counts,
					'price' => $pro_result['price'],
					'clean_price' => $pro_result['price']
				);

				$product_id_order[] = $data;


				$data_product = array(
					'count' =>	$ost
				);
				$product->update($data_product, 'id ='.$item['product_id']);
			
			/*$sum_pod_new = $pro_result['price'] * $counts;
			$total_cost = $total_cost + $sum_pod_new;
			$orders = OrdersPeer::getInstance();
			$dt = array(
				'total_cost' => $total_cost
			);
			$orders->update($dt, 'id ='.$new_order_id);*/
		}

		foreach($product_id_order as $ord_row){
			$order2product->insert($ord_row);
		}
	}

	/**
	 * Set delivery columns.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _delivery($row)
	{
		// Get delivery row
		$delivery = $row->getDeliveryRowByDeliveryId();
		$isNew = 0;
		if (!$delivery) {
			$delivery = DeliveryPeer::getInstance()->createRow();
			$isNew = 1;
		}

		$params = array(
			'email' => 'email',
			'телефон' => 'phone',
			'имя' => 'firstName',
			'фамилия' => 'lastName',
			'город' => 'city',
			'улица' => 'street',
			'дом' => 'home',
			'корпус' => 'corps',
			'подъезд' => 'porch',
			'этаж' => 'level',
			'квартира' => 'flat',
			'метро' => 'metroId',
			'внутри МКАД' => 'inMkad',
		);

		// Check for required field is filled or throw exception
		$required = array(
			'firstName' => 'имя',
			'lastName' => 'фамилия',
			'phone' => 'телефон',
			'city' => 'город',
			'street' => 'улица',
			'home' => 'дом',
		);

		$erFields = array();
		foreach ($required as $key => $value) {
			if (!$this->_getParam($key)) {
				$erFields[] = $value;
			}
		}

		if ($erFields) {
			$erFields = implode(', ', $erFields);
			throw new Crud_Exception('Заполните обязательные поля: ' . $erFields);
		}

		// Check changed columns
		$changed = array();
		foreach ($params as $key => $param) {
			$get = 'get' . ucfirst($param);
			$value = $delivery->$get();

			if ($value != $this->_getParam($param)) {
				$changed[] = $key;
			}
		}

		// Create new delivery is some value is changed AND delivery has 2 or many orders
		if ($changed) {
			$select = OrdersPeer::getInstance()->select();
			$select->where(OrdersPeer::DELIVERY_ID, $delivery->getId());
			$select->limit(2);
			$rowset = OrdersPeer::getInstance()->fetchAll($select);
			if ($rowset->count() > 1) {
				$nDelivery = DeliveryPeer::getInstance()->createRow();
				if ($delivery->getProfileId()) {
					$nDelivery->setProfileId($delivery->getProfileId());
				}

				$isNew = 1;
				$delivery = $nDelivery;
			}
		}

		// Set new values
		foreach ($params as $param) {
			$value = $this->_getParam($param);
			if ($value == '') $value = null;
			$method = 'set' . ucfirst($param);
			$delivery->$method($value);
		}

		// Save row and update orders
		$delivery->save();
		if ($isNew) {
			$row->setDeliveryId($delivery->getId());
		}

		// Save fio in row
		$row->setFio($delivery->getFirstName() . ' ' . $delivery->getLastName());
		$row->save();

		// Add log
		if ($changed) {
			$changed = implode(', ', $changed);
			$row->addLog('%s изменил поля ' . $changed);
		}
	}

	/**
	 * Add operator comment to order.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _comment($row)
	{
		$comment = $this->_getParam('operator_comment');
		if (!$comment) {
			return;
		}

		$user = $this->_getAdminUser();

		$cRow = OrderCommentPeer::getInstance()->createRow();
		$cRow->setOrderId($row->getId());
		$cRow->setComment($comment);
		$cRow->setAdminUserId($user->getId());
		$cRow->save();

		$row->addLog('%s добавил комментарий');
	}

	/**
	 * Add and delete product to order. And set log.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _order2product($row)
	{

		if (!$row->isProductCompositionModifiedAvailable()) {
			return;
		}

		$this->_order2productDelete($row);
		$this->_order2productEditCount($row);
		$this->_order2productAdd($row);

		$rowset = $row->getOrder2productRowsetByOrderId();
		$count = 0;
		foreach ($rowset as $o2p) {
			$count += $o2p->getCount();
		}

		if (!$count) {
			throw new Crud_Exception('Добавьте хотя бы один товар в заказ');
		}

		if ($this->_changed) {
			OrdersService::getInstance()->calculatePrice($row);
			OrdersService::getInstance()->calculateWeight($row);
			$row->addLog('%s изменил состав заказа');
		}
	}

	/**
	 * Delete products from order.
	 *
	 * @param OrderRow $row
	 * @return void
	 */
	protected function _order2productDelete($row)
	{
		$delete = $this->_getParam('product_callcenter_delete', array());
		foreach ($delete as $internalId) {
			$product = ProductPeer::getInstance()->findByInternalId($internalId)->current();
			$select = Order2productPeer::getInstance()->select();
			$select->where(Order2productPeer::PRODUCT_ID, $product->getId());
			$select->where(Order2productPeer::ORDER_ID, $row->getId());
			$o2p = Order2productPeer::getInstance()->fetchRow($select);
			if (!$o2p) {
				continue;
			}

			// Return product count
			$count = $product->getCount();
			$count += $o2p->getCount();
			$product->setCount($count);
			$product->save();

			// Delete many2many
			$o2p->delete();

			$this->_changed = 1;
		}
	}

	/**
	 * Edit count in order2product.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _order2productEditCount($row)
	{
		$edit = $this->_getParam('product_callcenter_count_edit', array());
		$peer = Order2productPeer::getInstance();

		foreach ($edit as $id => $count) {
			$select = $peer->select();
			$select->where(Order2productPeer::PRODUCT_ID, $id);
			$select->where(Order2productPeer::ORDER_ID, $row->getId());
			$o2p = $peer->fetchRow($select);



			$product = $o2p->getProductRowByProductId();
			$neededCount = $count - $o2p->getCount();

			if ($count == 0) {
				throw new Crud_Exception("{$product->getName()} было заказано , с нулевым остатком (Остаток у этого товара на складе) {$o2p->getCount()}");
			}

			if ($product->getCount() < $neededCount) {
				throw new Crud_Exception("{$product->getName()} было заказано {$o2p->getCount()}, нужно зарезервировать еще $neededCount, но в наличии только {$product->getCount()}");
			}

			if ($neededCount == 0) {
				continue;
			}

			// Изменяем остатки у товара
			$product->setCount(new Zend_Db_Expr("product.count - $neededCount"));
			$product->save();

			// Изменяем остатки у связки
			$o2p->setCount($count);
			$o2p->setDesiredCount($count);
			$o2p->save();

			$this->_changed = 1;
		}
	}

	/**
	 * Add products to order.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _order2productAdd($row)
	{
		$idArray = $this->_getParam('product_callcenter_id', array());
		$countArray = $this->_getParam('product_callcenter_count', array());

		foreach ($idArray as $key => $internalId) {
			$count = isset($countArray[$key]) ? $countArray[$key] : null;
			if (!$internalId || !$count) continue;

			$product = ProductPeer::getInstance()->findByInternalId($internalId)->current();
			if (!$product) {
				continue;
			}

			if ($product->getCount() < $count) {
				throw new Crud_Exception("{$product->getName()} заказано $count, но в наличии только {$product->getCount()}");
			}

			// Резервируем остатки, если она уже обновились
			if ($product->getRestsAt() >= $row->getCreatedAt()) {
				//continue;
			}
			$product->setCount(new Zend_Db_Expr("product.count - $count"));
			$product->save();

			// Save many2many
			$o2pRow = Order2productPeer::getInstance()->createRow();
			$o2pRow->setProductId($product->getId());
			$o2pRow->setCount($count);
			$o2pRow->setDesiredCount($count);
			$o2pRow->setOrderId($row->getId());
			$o2pRow->save();

			$this->_changed = 1;
		}
	}

	/**
	 * Call service method (create file for domino)
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _toFile($row)
	{
		$status = OrderStatusPeer::getInstance()->fetchByKey('approved');
		$this->_salesCountInc($row);
		if (($row->getOrderStatusId() == $status->getId()) && $this->_getParam('submit')) {
			$params['bonus'] = $this->_bonused($row);
			OrdersService::getInstance()->ordersToFile($row);
			OrdersService::getInstance()->notifyOrderCreated($row, array(), $params);
		}
	}

	protected function _bonused($row)
	{
		$status = OrderStatusPeer::getInstance()->fetchByKey('approved');
		$result = null;
		if (($row->getOrderStatusId() == $status->getId()) && $this->_getParam('submit')) {
			$rowset = LotteryService::getInstance()->getOrderBonusByOrder($row);
			$t = time();
			//чтобы акция стартовала когда необходимо
			if (0 == $rowset->count() && $t >= strtotime('2011-06-01') && $t <= strtotime('2011-06-30')
			) {
				$result = LotteryService::getInstance()->createBonusByOrder($row);
				//@todo отослать email о том что у него бонус??
			}
		}
		return $result;
	}

	/**
	 * Увеличиваем число продаж всем продуктам.
	 *
	 * @param OrdersRow $row
	 * @return void
	 */
	protected function _salesCountInc($row)
	{
		$products = $row->getProductRowsetByOrder2product();
		foreach ($products as $product) {
			$product->setSalesCount($product->getSalesCount() + 1);
			$product->save();
		}
	}

}


